[Ruby on Rails]AdminLTEをテンプレートとして使用する(2) – クライアントの実装
はじめに
前回に引き続き、RailsでAdminLTEをテンプレートとして使用する方法についてです。今回は前回解説したアプリのクライアント側の実装方法について書いていきたいと思います。
実装方法
1.フォルダ作成
まずはアプリのフォルダを作成します。前回書いたようにサーバとクライアントではフォルダを分けるので、アプリのルートとなるフォルダ配下に「client」フォルダを作成します。
2.ライブラリの配置
AdminLTEのページの「Download」ボタンを押下してライブラリとサンプルソースをダウンロードします。今回はAdminLTE自体のソースを変更しないので「Ready」の方をダウンロードしました。
clientフォルダ内にライブラリを配置するフォルダを作成します。前回書いたようにlibフォルダを作成し、その中にadminlteフォルダを作成してください。
ダウンロードしたzipを解凍すると、中にライブラリとサンプルソースがあります。これらから「bootstrap」「dist」「plugins」フォルダをlib/adminlteフォルダにコピーします。以下の様なフォルダ構成になるはずです。
. ├── client │ ├── lib │ │ └── adminlte │ │ ├── bootstrap │ │ ├── dist │ │ ├── plugins
3.starter.html
先ほどのサンプルにstarter.htmlがあります。これをclientフォルダへコピーします。そしてlib/adminlteフォルダ内のライブラリを参照するよう、html内のstylesheetやjavascriptの参照先を変更します。以下のようになります。
<!DOCTYPE html> <!-- This is a starter template page. Use this page to start your new project from scratch. This page gets rid of all links and provides the needed markup only. --> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AdminLTE 2 | Starter</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <!-- Bootstrap 3.3.5 --> <link rel="stylesheet" href="lib/adminlte/bootstrap/css/bootstrap.min.css"> <!-- Font Awesome --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"> <!-- Ionicons --> <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <!-- Theme style --> <link rel="stylesheet" href="lib/adminlte/dist/css/AdminLTE.min.css"> <!-- AdminLTE Skins. We have chosen the skin-blue for this starter page. However, you can choose any other skin. Make sure you apply the skin class to the body tag so the changes take effect. --> <link rel="stylesheet" href="lib/adminlte/dist/css/skins/skin-blue.min.css"> (中略) <!DOCTYPE html> <!-- This is a starter template page. Use this page to start your new project from scratch. This page gets rid of all links and provides the needed markup only. --> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AdminLTE 2 | Starter</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <!-- Bootstrap 3.3.5 --> <link rel="stylesheet" href="lib/adminlte/bootstrap/css/bootstrap.min.css"> <!-- Font Awesome --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"> <!-- Ionicons --> <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <!-- Theme style --> <link rel="stylesheet" href="lib/adminlte/dist/css/AdminLTE.min.css"> <!-- AdminLTE Skins. We have chosen the skin-blue for this starter page. However, you can choose any other skin. Make sure you apply the skin class to the body tag so the changes take effect. --> <link rel="stylesheet" href="lib/adminlte/dist/css/skins/skin-blue.min.css">
4.chartjs.html
chartjs.htmlについてもサンプルから流用します。pages/chartsフォルダを作成し、サンプルのchartjs.htmlをコピーしてください。
コピーしたらstarter.htmlと同様、stylesheetやjavascriptの参照先を変更します。以下のようになります。(全ての修正箇所は網羅できていないかもしれません)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AdminLTE 2 | ChartJS</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <!-- Bootstrap 3.3.5 --> <link rel="stylesheet" href="../../lib/adminlte/bootstrap/css/bootstrap.min.css"> <!-- Font Awesome --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"> <!-- Ionicons --> <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <!-- Theme style --> <link rel="stylesheet" href="../../lib/adminlte/dist/css/AdminLTE.min.css"> <!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. --> <link rel="stylesheet" href="../../lib/adminlte/dist/css/skins/_all-skins.min.css"> (中略) <!-- jQuery 2.1.4 --> <script src="../../lib/adminlte/plugins/jQuery/jQuery-2.1.4.min.js"></script> <!-- Bootstrap 3.3.5 --> <script src="../../lib/adminlte/bootstrap/js/bootstrap.min.js"></script> <!-- ChartJS 1.0.1 --> <script src="../../lib/adminlte/plugins/chartjs/Chart.min.js"></script> <!-- FastClick --> <script src="../../lib/adminlte/plugins/fastclick/fastclick.min.js"></script> <!-- AdminLTE App --> <script src="../../lib/adminlte/dist/js/app.min.js"></script> <!-- AdminLTE for demo purposes --> <script src="../../lib/adminlte/dist/js/demo.js"></script> (以下略)
次にデータの取得とグラフの表示です。サンプルではJavaScriptで固定のデータを表示していますが、chartjs.htmlではサーバよりデータを取得するようにします。サーバとの通信はベーシックなjQueryで行います(jQueryがAdminLTEのライブラリに入っていることもある)。以下の様なソースとなります。
<script> $(function () { $.getJSON( 'http://localhost:3000/api/v1/pages/charts/chartjs/area_chart.json', function(data) { //-------------- //- AREA CHART - //-------------- // Get context with jQuery - using jQuery's .get() method. var areaChartCanvas = $("#areaChart").get(0).getContext("2d"); // This will get the first returned node in the jQuery collection. var areaChart = new Chart(areaChartCanvas); var areaChartData = data; var areaChartOptions = { //Boolean - If we should show the scale at all showScale: true, //Boolean - Whether grid lines are shown across the chart scaleShowGridLines: false, //String - Colour of the grid lines scaleGridLineColor: "rgba(0,0,0,.05)", //Number - Width of the grid lines scaleGridLineWidth: 1, //Boolean - Whether to show horizontal lines (except X axis) scaleShowHorizontalLines: true, //Boolean - Whether to show vertical lines (except Y axis) scaleShowVerticalLines: true, //Boolean - Whether the line is curved between points bezierCurve: true, //Number - Tension of the bezier curve between points bezierCurveTension: 0.3, //Boolean - Whether to show a dot for each point pointDot: false, //Number - Radius of each point dot in pixels pointDotRadius: 4, //Number - Pixel width of point dot stroke pointDotStrokeWidth: 1, //Number - amount extra to add to the radius to cater for hit detection outside the drawn point pointHitDetectionRadius: 20, //Boolean - Whether to show a stroke for datasets datasetStroke: true, //Number - Pixel width of dataset stroke datasetStrokeWidth: 2, //Boolean - Whether to fill the dataset with a color datasetFill: true, //String - A legend template legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>", //Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container maintainAspectRatio: true, //Boolean - whether to make the chart responsive to window resizing responsive: true }; //Create the line chart areaChart.Line(areaChartData, areaChartOptions); //------------- //- LINE CHART - //-------------- var lineChartCanvas = $("#lineChart").get(0).getContext("2d"); var lineChart = new Chart(lineChartCanvas); var lineChartOptions = areaChartOptions; lineChartOptions.datasetFill = false; lineChart.Line(areaChartData, lineChartOptions); //------------- //- BAR CHART - //------------- var barChartCanvas = $("#barChart").get(0).getContext("2d"); var barChart = new Chart(barChartCanvas); var barChartData = areaChartData; barChartData.datasets[1].fillColor = "#00a65a"; barChartData.datasets[1].strokeColor = "#00a65a"; barChartData.datasets[1].pointColor = "#00a65a"; var barChartOptions = { //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value scaleBeginAtZero: true, //Boolean - Whether grid lines are shown across the chart scaleShowGridLines: true, //String - Colour of the grid lines scaleGridLineColor: "rgba(0,0,0,.05)", //Number - Width of the grid lines scaleGridLineWidth: 1, //Boolean - Whether to show horizontal lines (except X axis) scaleShowHorizontalLines: true, //Boolean - Whether to show vertical lines (except Y axis) scaleShowVerticalLines: true, //Boolean - If there is a stroke on each bar barShowStroke: true, //Number - Pixel width of the bar stroke barStrokeWidth: 2, //Number - Spacing between each of the X value sets barValueSpacing: 5, //Number - Spacing between data sets within X values barDatasetSpacing: 1, //String - A legend template legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>", //Boolean - whether to make the chart responsive responsive: true, maintainAspectRatio: true }; barChartOptions.datasetFill = false; barChart.Bar(barChartData, barChartOptions); } ); $.getJSON( 'http://localhost:3000/api/v1/pages/charts/chartjs/pie.json', function(data) { //------------- //- PIE CHART - //------------- // Get context with jQuery - using jQuery's .get() method. var pieChartCanvas = $("#pieChart").get(0).getContext("2d"); var pieChart = new Chart(pieChartCanvas); var pieOptions = { //Boolean - Whether we should show a stroke on each segment segmentShowStroke: true, //String - The colour of each segment stroke segmentStrokeColor: "#fff", //Number - The width of each segment stroke segmentStrokeWidth: 2, //Number - The percentage of the chart that we cut out of the middle percentageInnerCutout: 50, // This is 0 for Pie charts //Number - Amount of animation steps animationSteps: 100, //String - Animation easing effect animationEasing: "easeOutBounce", //Boolean - Whether we animate the rotation of the Doughnut animateRotate: true, //Boolean - Whether we animate scaling the Doughnut from the centre animateScale: false, //Boolean - whether to make the chart responsive to window resizing responsive: true, // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container maintainAspectRatio: true, //String - A legend template legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>" }; //Create pie or douhnut chart // You can switch between pie and douhnut using the method below. pieChart.Doughnut(data, pieOptions); } ); }); </script>
ちょっと長いですが、大きく2つに分かれます。getJSON()で囲まれている3行目〜110行目までと、112行目以降です。
3行目〜110行目までは「http://localhost:3000/api/v1/pages/charts/chartjs/area_chart.json」にアクセスし、コールバック内で取得したJSONデータをAreaChart、LineChart、BarChartに設定しています。
112行目は「http://localhost:3000/api/v1/pages/charts/chartjs/pie.json」にアクセスし、コールバック内でPieチャートにデータを設定しています。
今回は「http://localhost:3000〜」とベタ書きしていますが、実案件ではこの辺は定数などに切り出した方がいいでしょう。
5.クライアントをWebサーバで動かす
クライアントをWebサーバ内で動かし、http〜でアクセスする方法についてです。starter.htmlについてはサーバと通信していないので、クライアントのみで動かすことができます。いろいろなWebサーバがありますが、今回はRubyのみで動かすことできる「WEBrick」を使用しました。ターミナルでclientフォルダへ移動し、以下のコマンドを実行します。
$ ruby -rwebrick -e 'WEBrick::HTTPServer.new({:DocumentRoot => "./", :Port => 8888}).start'
ポートは8888で起動しています。この状態でブラウザより「http://localhost:8888/starter.html」でアクセスすると、以下の様が画面が表示されるはずです。
まとめ
クライアント側の実装について見てきました。クライアントをサーバから分離したことにより、サンプルから流用したhtmlファイルの修正箇所が少なく済んだかと思います。特にchartjs.htmlのJavaScriptについては、getJSON()のコールバック内のソースはサンプルをほとんど変更することなく実装できています。
次回、サーバ側の実装について書いていきたいと思います。